﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Windows.Controls;

namespace Cloak.Mvvm.Navigation
{
	/// <summary>
	/// A cache of a map of page types to view models
	/// </summary>
	public sealed class CachingPageModelMap : IPageModelMap
	{
		private readonly IPageModelMap _innerMap;
		private readonly IDictionary<Type, PageModelReference> _mappings = new Dictionary<Type, PageModelReference>();

		/// <summary>
		/// Initializes an instance of <see cref="CachingPageModelMap"/> with the specified inner map
		/// </summary>
		/// <param name="innerMap">The map which is used to populate the cache</param>
		public CachingPageModelMap(IPageModelMap innerMap)
		{
			Contract.Requires(innerMap != null);

			_innerMap = innerMap;
		}

		#region IPageModelMap
		/// <summary>
		/// Calculates the view model reference if it has not been requested before, or returns a previously-calculated reference if it has
		/// </summary>
		/// <param name="pageType">The type of page to map to a view model</param>
		/// <returns>A reference to the view model mapped to the page type, or null if the page type is not associated with a view model</returns>
		public PageModelReference GetPageModelReference(Type pageType)
		{
			PageModelReference pageModelReference;

			lock(_mappings)
			{
				if(!_mappings.TryGetValue(pageType, out pageModelReference))
				{
					pageModelReference = _innerMap.GetPageModelReference(pageType);

					_mappings[pageType] = pageModelReference;
				}
			}

			return pageModelReference;
		}
		#endregion
	}
}